#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>


/************************************************
*	Definicion de los tipos de datos	*
************************************************/

typedef struct nodo_arbol nodo_arbol_t;

typedef int (*abb_nodo_comparar_clave_t) (const char *, const char *);
typedef void (*abb_nodo_destruir_dato_t) (void *);

/************************************************
*		Primitivas del nodo_arbol	*
************************************************/

nodo_arbol_t* nodo_crear(const char* clave, void* dato);

nodo_arbol_t* buscar_maximo(nodo_arbol_t* nodo);

nodo_arbol_t* buscar_minimo(nodo_arbol_t* nodo);

nodo_arbol_t* buscar_nodo_padre(abb_nodo_comparar_clave_t cmp,nodo_arbol_t* padre_anterior,nodo_arbol_t* raiz,nodo_arbol_t* nodo_hijo);

nodo_arbol_t* buscar_nodo(abb_nodo_comparar_clave_t cmp,nodo_arbol_t* nodo,const char* clave);

bool nodo_es_mayor(nodo_arbol_t* nodo1,nodo_arbol_t* nodo2, abb_nodo_comparar_clave_t cmp);

int nodo_comparar(nodo_arbol_t* nodo1,nodo_arbol_t* nodo2, abb_nodo_comparar_clave_t cmp);

bool nodos_ordenados(nodo_arbol_t* nodo, abb_nodo_comparar_clave_t cmp);

void intercambiar_nodos(nodo_arbol_t* nodo1, nodo_arbol_t* nodo2);

/***********************************************************
	ACCESO/ESCRITURA A DATOS DEL NODO
***********************************************************/
void nodo_agregar_dato(nodo_arbol_t* nodo,void* dato,abb_nodo_destruir_dato_t destruir_dato);

void* nodo_ver_dato(nodo_arbol_t* nodo);

void nodo_agregar_hijo_izq(nodo_arbol_t* nodo,nodo_arbol_t* nodo_hijo);

void nodo_agregar_hijo_der(nodo_arbol_t* nodo,nodo_arbol_t* nodo_hijo);

nodo_arbol_t* nodo_ver_hijo_izq(nodo_arbol_t* nodo);

nodo_arbol_t* nodo_ver_hijo_der(nodo_arbol_t* nodo);

bool nodo_tiene_hijos(nodo_arbol_t* nodo);

/**********************************************************
			DESTRUCTOR
**********************************************************/
void nodo_destruir(nodo_arbol_t* nodo, abb_nodo_destruir_dato_t destruir_dato);

void nodo_destruir_sin_dato(nodo_arbol_t* nodo);

void nodo_destruir_en_cadena(nodo_arbol_t* nodo,abb_nodo_destruir_dato_t destruir_dato);

/**********************************************************
                UTILES
**********************************************************/

void in_orden(nodo_arbol_t *nodo, bool visitar(const char *, void *, void *),void *extra);

abb_iter_t *nodo_iter_in_crear(nodo_arbol_t *nodo);

void nodo_iter_in_destruir(abb_iter_t *iter);

const char *nodo_iter_ver_actual(const abb_iter_t *iter);

bool nodo_iter_al_final(const abb_iter_t *iter);

bool nodo_iter_avanzar(abb_iter_t *iter);
